﻿using Auto.AlgsAndPush.Entities;
using Auto.AlgsAndPush.Models;
using Auto.AlgsAndPush.Services.DeviceType;
using Auto.AlgsAndPush.Services.ResultFilter;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Auto.AlgsAndPush.Services
{
    public class FilterMQProcessService
    {
        private readonly ILogger _logger;
        private readonly MetroContext _context;
        private readonly HttpClientService _httpClient;
        private readonly FilterProcessService _filterProcessService;

        public FilterMQProcessService(ILogger<FilterMQProcessService> logger, MetroContext context, HttpClientService httpClient, FilterProcessService filterProcessService)
        {
            _logger = logger;
            _context = context;
            _httpClient = httpClient;
            _filterProcessService = filterProcessService;
        }

        public async Task Start(SubProject subProject)
        {
            // 1.判断type, dist和hydrolevel的处理，其余忽略
            var type = TypeFactory.GenerateType(_httpClient, subProject.Type);

            if (type == null) return;

            // 2.获取该项目的滤波配置和测量计划配置
            var filterConfigs = _context.AutoSyncConfig
                .Where(x => x.AutoProjectId == subProject.AutoProjectId && x.Type.Value == (int)subProject.Type)
                .ToList();
            if (filterConfigs.Count() == 0) return;

            var momentConfigs = _context.AutoMomentConfig
                .Where(x => x.AutoProjectId == subProject.AutoProjectId)
                .Select(c => c.Moment).ToList();


            foreach (var config in filterConfigs)
            {
                // 3.在每一个配置中，判断当前测完的数据是否是当前配置的最后一期数据，如果不是结束本次循环
                TimeCalculator.Calculate(config, subProject.DateTime, out DateTime startTime, out DateTime endTime);
                TimeCalculator.GetConfigLastMoment(momentConfigs, endTime, out DateTime lastMoment);
                if (lastMoment < startTime || Math.Abs((subProject.DateTime - lastMoment).TotalMinutes) >= 5)
                    continue;

                // 4.如果是继续，保存该条滤波记录AutoAsyncRecord,status=running
                var existRecord = _context.AutoSyncRecord
                    .FirstOrDefault(x => x.AutoSyncConfigId == config.Id && x.AutoProjectId == subProject.AutoProjectId && x.DateTime == subProject.DateTime);
                if (existRecord != null)
                {
                    _context.AutoSyncRecord.Remove(existRecord);
                }
                var newRecord = new AutoSyncRecord
                {
                    AutoProjectId = subProject.AutoProjectId,
                    AutoSyncConfigId = config.Id,
                    DateTime = subProject.DateTime,
                    Numbers = "",
                    Status = StatusEnum.Running
                };
                _context.AutoSyncRecord.Add(newRecord);
                _context.SaveChanges();

                try
                {
                    // 5.拉取该配置的所有期数据
                    _logger.LogInformation($"{subProject.AutoProjectId}测组拉取{startTime}--{endTime}数据");
                    var multiResults = await type.PullMultiNumberResultsAsync(subProject.AutoProjectId, startTime, endTime);

                    // 6.如果没有数据status=PullingNoData，结束本次循环
                    if (!multiResults.Any())
                    {
                        _logger.LogWarning($"在{startTime}--{endTime}没有对应的数据");
                        newRecord.Status = StatusEnum.PullingNoData;
                        _context.SaveChanges();
                        continue;
                    }

                    // 7.如果有数据，进行数据滤波
                    _logger.LogInformation($"开始滤波处理");
                    var filterRets = _filterProcessService.ProcessMultiOriginResults(multiResults);

                    // 8.将滤波后的数据返回到原数据库中
                    _logger.LogInformation($"开始将滤波数据存入原数据库中");
                    var ret = await type.PushFilterResultAsync(subProject.AutoProjectId, filterRets);

                    // 9.更新滤波数据的期数到AutoAsyncRecord
                    newRecord.Numbers = string.Join(',', multiResults.Select(r => r.Number));
                    if (ret)
                    {
                        newRecord.Status = StatusEnum.Completed;
                    }
                    else
                    {
                        newRecord.Status = StatusEnum.Fault;
                        _logger.LogError($"{subProject.AutoProjectId}测组，滤波数据存入数据库失败！");
                    }
                }
                catch (Exception e)
                {
                    if (e.Message == StatusEnum.PullingFault) newRecord.Status = StatusEnum.PullingFault;
                    else if (e.Message == StatusEnum.FilteringFault) newRecord.Status = StatusEnum.FilteringFault;
                    else newRecord.Status = StatusEnum.Fault;
                }
                finally
                {
                    _context.SaveChanges();
                    _logger.LogInformation($"{DateTime.Now}:已完成{subProject.AutoProjectId}测组--{lastMoment}数据的滤波处理");
                }

            }
        }
    }
}
